/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "disc_server_proxy.h"

#include <mutex>

#include "ipc_skeleton.h"
#include "disc_log.h"
#include "disc_server_proxy_standard.h"
#include "message_parcel.h"
#include "softbus_errcode.h"
#include "softbus_server_ipc_interface_code.h"
#include "softbus_service_discovery.h"

using namespace OHOS;

namespace {
sptr<DiscServerProxy> g_serverProxy = nullptr;
static uint32_t g_getSystemAbilityId = 2;
const std::u16string SAMANAGER_INTERFACE_TOKEN = u"ohos.samgr.accessToken";
std::mutex g_mutex;
}

static sptr<IRemoteObject> GetSystemAbility()
{
    MessageParcel data;

    if (!data.WriteInterfaceToken(SAMANAGER_INTERFACE_TOKEN)) {
        return nullptr;
    }

    data.WriteInt32(SOFTBUS_SERVER_SA_ID_INNER);
    MessageParcel reply;
    MessageOption option;
    sptr<IRemoteObject> samgr = IPCSkeleton::GetContextObject();
    DISC_CHECK_AND_RETURN_RET_LOGE(samgr != nullptr, nullptr, DISC_SDK, "remote is nullptr");

    int32_t err = samgr->SendRequest(g_getSystemAbilityId, data, reply, option);
    DISC_CHECK_AND_RETURN_RET_LOGE(err == 0, nullptr, DISC_SDK, "Get GetSystemAbility failed=%{public}d", err);
    return reply.ReadRemoteObject();
}

int32_t DiscServerProxyInit(void)
{
    std::lock_guard<std::mutex> lock(g_mutex);
    DISC_CHECK_AND_RETURN_RET_LOGE(g_serverProxy == nullptr, SOFTBUS_OK, DISC_SDK, "Init success");
    sptr<IRemoteObject> object = GetSystemAbility();
    DISC_CHECK_AND_RETURN_RET_LOGE(object != nullptr, SOFTBUS_DISCOVER_GET_REMOTE_FAILED, DISC_SDK,
        "Get remote softbus object failed");

    g_serverProxy = new (std::nothrow) DiscServerProxy(object);
    DISC_CHECK_AND_RETURN_RET_LOGE(g_serverProxy != nullptr, SOFTBUS_SERVER_NOT_INIT, DISC_SDK,
        "Create disc server proxy failed");

    int ret = g_serverProxy->DiscServerProxyStandardInit();
    DISC_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_SERVER_NOT_INIT, DISC_SDK,
        "Create disc server proxy standard failed");
    return SOFTBUS_OK;
}

void DiscServerProxyDeInit(void)
{
    std::lock_guard<std::mutex> lock(g_mutex);
    DISC_CHECK_AND_RETURN_LOGE(g_serverProxy != nullptr, DISC_SDK, "g_serverProxy is nullptr");
    g_serverProxy->DiscServerProxyStandardDeInit();
    g_serverProxy.clear();
}

int32_t ServerIpcRegisterService(const ServiceInfo *serviceInfo)
{
    DISC_CHECK_AND_RETURN_RET_LOGE(g_serverProxy != nullptr, SOFTBUS_SERVER_NOT_INIT, DISC_SDK,
        "g_serverProxy is nullptr");

    int32_t ret = g_serverProxy->RegisterService(serviceInfo);
    if (ret != 0) {
        DISC_LOGE(DISC_SDK, "RegisterService failed");
    }
    return ret;
}

int32_t ServerIpcUnRegisterService(const char *serviceId)
{
    DISC_CHECK_AND_RETURN_RET_LOGE(g_serverProxy != nullptr, SOFTBUS_SERVER_NOT_INIT, DISC_SDK,
        "g_serverProxy is nullptr");

    int32_t ret = g_serverProxy->UnRegisterService(serviceId);
    if (ret != 0) {
        DISC_LOGE(DISC_SDK, "UnRegisterService failed");
    }
    return ret;
}

int32_t ServerIpcUpdateService(const ServiceInfo *serviceInfo)
{
    DISC_CHECK_AND_RETURN_RET_LOGE(g_serverProxy != nullptr, SOFTBUS_SERVER_NOT_INIT, DISC_SDK,
        "g_serverProxy is nullptr");

    int32_t ret = g_serverProxy->UpdateService(serviceInfo);
    if (ret != 0) {
        DISC_LOGE(DISC_SDK, "UpdateService failed");
    }
    return ret;
}
